#include "interface.h"

#include <QtGui\QGridLayout>
#include <QGroupBox>
#include <QLabel>

PlanetSystemDialog::PlanetSystemDialog(MathModel* pMathModel, QWidget* parent /*= NULL*/) 
  : QDialog(parent)
  , m_pMathModel(pMathModel)
{
  setWindowTitle("System overview");
  inputStringDialog = new InputStringDialog("Input new name", this);
  inputStringDialog->hide();
  connect(inputStringDialog, SIGNAL(stringChanged()), this, SLOT(newName()));

  planetsComboBox = new QComboBox(this);
  for (unsigned i = 0; i < m_pMathModel->planetSystem.size(); ++i)
    planetsComboBox->addItem(m_pMathModel->planetSystem[i].name);
  planetsComboBox->setCurrentIndex(0);
  connect(planetsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectPlanet(int)));

  QGroupBox* physicalParameters = new QGroupBox("Physical parameters", this);
  QGridLayout* physLayout = new QGridLayout();

  QGroupBox* position = new QGroupBox("position", this);
  QGridLayout* posLayout = new QGridLayout();
  xEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].r.x);
  yEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].r.y);
  zEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].r.z);
  posLayout->addWidget(xEdit, 0, 0, 1, 1);
  posLayout->addWidget(yEdit, 1, 0, 1, 1);
  posLayout->addWidget(zEdit, 2, 0, 1, 1);
  position->setLayout(posLayout);

  QGroupBox* velocity = new QGroupBox("velocity", this);
  QGridLayout* velLayout = new QGridLayout();
  vxEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].v.x);
  vyEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].v.y);
  vzEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].v.z);
  velLayout->addWidget(vxEdit, 0, 0, 1, 1);
  velLayout->addWidget(vyEdit, 1, 0, 1, 1);
  velLayout->addWidget(vzEdit, 2, 0, 1, 1);
  velocity->setLayout(velLayout);

  QLabel* massLabel = new QLabel("Mass = ");
  massEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].m);

  physLayout->addWidget(position, 0, 0, 3, 1);
  physLayout->addWidget(velocity, 0, 1, 3, 1);
  physLayout->addWidget(massLabel, 3, 0, 1, 1, Qt::AlignRight);
  physLayout->addWidget(massEdit, 3, 1, 1, 1);
  physicalParameters->setLayout(physLayout);
  
  QGroupBox* graphParameters = new QGroupBox("Drawing parameters", this);
  QGridLayout* graphLayout = new QGridLayout();
  QLabel* radLabel = new QLabel("Radius = ");
  radEdit = new RealNumTextEdit(m_pMathModel->planetSystem[0].rad);
  connect(radEdit, SIGNAL(textChanged()), this, SLOT(radChanged()));

  QLabel* redLabel = new QLabel("Red : ");
  redEdit = new RealNumTextEdit((m_pMathModel->planetSystem[0].color & 0xff0000) >> 16);
  connect(redEdit, SIGNAL(textChanged()), this, SLOT(redChanged()));

  QLabel* greenLabel = new QLabel("Green : ");
  greenEdit = new RealNumTextEdit((m_pMathModel->planetSystem[0].color & 0x00ff00) >> 8);
  connect(greenEdit, SIGNAL(textChanged()), this, SLOT(greenChanged()));

  QLabel* blueLabel = new QLabel("Blue : ");
  blueEdit = new RealNumTextEdit((m_pMathModel->planetSystem[0].color & 0x0000ff));
  connect(blueEdit, SIGNAL(textChanged()), this, SLOT(blueChanged()));

  graphLayout->addWidget(radLabel, 0, 0, 1, 1);
  graphLayout->addWidget(radEdit, 0, 1, 1, 1);
  graphLayout->addWidget(redLabel, 1, 0, 1, 1);
  graphLayout->addWidget(redEdit, 1, 1, 1, 1);
  graphLayout->addWidget(greenLabel, 2, 0, 1, 1);
  graphLayout->addWidget(greenEdit, 2, 1, 1, 1);
  graphLayout->addWidget(blueLabel, 3, 0, 1, 1);
  graphLayout->addWidget(blueEdit, 3, 1, 1, 1);
  graphParameters->setLayout(graphLayout);

  renameButton = new QPushButton("Rename");
  connect(renameButton, SIGNAL(clicked()), this, SLOT(renamePlanet()));
  addButton = new QPushButton("Add");
  connect(addButton, SIGNAL(clicked()), this, SLOT(addPlanet()));
  removeButton = new QPushButton("Remove");
  connect(removeButton, SIGNAL(clicked()), this, SLOT(removePlanet()));

  QGridLayout* pLayout = new QGridLayout();
  pLayout->addWidget(planetsComboBox, 0, 0, 1, 1);
  pLayout->addWidget(physicalParameters, 0, 1, 4, 2);
  pLayout->addWidget(graphParameters, 0, 3, 4, 2);
  pLayout->addWidget(renameButton, 2, 0, 1, 1);
  pLayout->addWidget(addButton, 3, 0, 1, 1);
  pLayout->addWidget(removeButton, 4, 0, 1, 1);

  planetsCollision = new QCheckBox("Planets collision", this);
  if (m_pMathModel->getCollisionState() == true)
    planetsCollision->setCheckState(Qt::Checked);
  else
    planetsCollision->setCheckState(Qt::Unchecked);
  connect(planetsCollision, SIGNAL(stateChanged(int)), this, SLOT(collisionStateChanged(int)));
  pLayout->addWidget(planetsCollision, 5, 0, 1, 1);

  setLayout(pLayout);


  connect(xEdit, SIGNAL(textChanged()), this, SLOT(xChanged()));
  connect(yEdit, SIGNAL(textChanged()), this, SLOT(yChanged()));
  connect(zEdit, SIGNAL(textChanged()), this, SLOT(zChanged()));
  
  connect(vxEdit, SIGNAL(textChanged()), this, SLOT(vxChanged()));
  connect(vyEdit, SIGNAL(textChanged()), this, SLOT(vyChanged()));
  connect(vzEdit, SIGNAL(textChanged()), this, SLOT(vzChanged()));

  connect(massEdit, SIGNAL(textChanged()), this, SLOT(massChanged()));
}

void PlanetSystemDialog::setMathModel(MathModel* pMathModel)
{
  for (int i = m_pMathModel->planetSystem.size() - 1; i >= 0; --i)
    planetsComboBox->removeItem(i);
  m_pMathModel = pMathModel;
  for (unsigned i = 0; i < m_pMathModel->planetSystem.size(); ++i)
    planetsComboBox->addItem(m_pMathModel->planetSystem[i].name);
  planetsComboBox->setCurrentIndex(0);
}
void PlanetSystemDialog::selectPlanet(int idx)
{
  if (idx >= 0)
  {
    xEdit->setValue(m_pMathModel->planetSystem[idx].r.x);
    yEdit->setValue(m_pMathModel->planetSystem[idx].r.y);
    zEdit->setValue(m_pMathModel->planetSystem[idx].r.z);

    vxEdit->setValue(m_pMathModel->planetSystem[idx].v.x);
    vyEdit->setValue(m_pMathModel->planetSystem[idx].v.y);
    vzEdit->setValue(m_pMathModel->planetSystem[idx].v.z);

    massEdit->setValue(m_pMathModel->planetSystem[idx].m);

    radEdit->setValue(m_pMathModel->planetSystem[idx].rad);
    redEdit->setValue((m_pMathModel->planetSystem[idx].color & 0xff0000) >> 16);
    greenEdit->setValue((m_pMathModel->planetSystem[idx].color & 0x00ff00) >> 8);
    blueEdit->setValue((m_pMathModel->planetSystem[idx].color & 0x0000ff));
  }
}

void PlanetSystemDialog::xChanged()
{
  bool ok;
  double x = xEdit->toPlainText().toDouble(&ok);
  if (ok && x != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.x)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.x = x;
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].path[0] = 
                                                        m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::yChanged()
{
  bool ok;
  double y = yEdit->toPlainText().toDouble(&ok);
  if (ok && y != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.y)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.y = y;
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].path[0] = 
                                                        m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::zChanged()
{
  bool ok;
  double z = zEdit->toPlainText().toDouble(&ok);
  if (ok && z != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.z)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r.z = z;
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].path[0] = 
                                                        m_pMathModel->planetSystem[planetsComboBox->currentIndex()].r;
    emit mathModelChanged();
  }
}

void PlanetSystemDialog::vxChanged()
{
  bool ok;
  double vx = vxEdit->toPlainText().toDouble(&ok);
  if (ok && vx != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.x)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.x = vx;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::vyChanged()
{
  bool ok;
  double vy = vyEdit->toPlainText().toDouble(&ok);
  if (ok && vy != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.y)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.y = vy;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::vzChanged()
{
  bool ok;
  double vz = vzEdit->toPlainText().toDouble(&ok);
  if (ok && vz != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.z)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].v.z = vz;
    emit mathModelChanged();
  }
}

void PlanetSystemDialog::massChanged()
{
  bool ok;
  double mass = massEdit->toPlainText().toDouble(&ok);
  if (ok && mass != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].m)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].m = mass;
    emit mathModelChanged();
  }
}

void PlanetSystemDialog::renamePlanet()
{
  int idx = planetsComboBox->currentIndex();
  inputStringDialog->setString(m_pMathModel->planetSystem[idx].name);
  inputStringDialog->show();
}

void PlanetSystemDialog::newName()
{
  int idx = planetsComboBox->currentIndex();
  m_pMathModel->planetSystem[idx].name = inputStringDialog->getString();
  planetsComboBox->removeItem(idx);
  planetsComboBox->insertItem(idx, m_pMathModel->planetSystem[idx].name);
  planetsComboBox->setCurrentIndex(idx);
  inputStringDialog->hide();
  emit planetNameChanged();
}

void PlanetSystemDialog::addPlanet()
{
  m_pMathModel->planetSystem.append(PlanetMath(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
                                    QString("Planet ") + QString::number(m_pMathModel->planetSystem.size())));
  planetsComboBox->addItem(QString("Planet ") + QString::number(m_pMathModel->planetSystem.size()));
  planetsComboBox->setCurrentIndex(m_pMathModel->planetSystem.size() - 1);
  emit mathModelChanged();
}
void PlanetSystemDialog::removePlanet()
{
  if (m_pMathModel->planetSystem.size() > 2)
  {
    int idx = planetsComboBox->currentIndex();
    m_pMathModel->planetSystem.removeAt(idx);
    planetsComboBox->removeItem(idx);
    emit mathModelChanged();
  }
}

void PlanetSystemDialog::collisionStateChanged(int state)
{
  if (state == 0)
    m_pMathModel->setCollisionState(false);
  else
    m_pMathModel->setCollisionState(true);
  emit mathModelChanged();
}

void PlanetSystemDialog::radChanged()
{
  bool ok;
  double rad = radEdit->toPlainText().toDouble(&ok);
  if (ok && rad != m_pMathModel->planetSystem[planetsComboBox->currentIndex()].rad)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].rad = rad;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::redChanged()
{
  bool ok;
  int color, colorR, colorG, colorB;
  colorR = (int)(redEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorG = (int)(greenEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorB = (int)(blueEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  color = (colorR << 16) + (colorG << 8) + colorB;
  if (colorR != (m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color & 0xff0000) >> 16)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color = color;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::greenChanged()
{
  bool ok;
  int color, colorR, colorG, colorB;
  colorR = (int)(redEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorG = (int)(greenEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorB = (int)(blueEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  color = (colorR << 16) + (colorG << 8) + colorB;
  if (colorG != (m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color & 0x00ff00) >> 8)
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color = color;
    emit mathModelChanged();
  }
}
void PlanetSystemDialog::blueChanged()
{
  bool ok;
  int color, colorR, colorG, colorB;
  colorR = (int)(redEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorG = (int)(greenEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  colorB = (int)(blueEdit->toPlainText().toDouble(&ok));
  if (!ok)
    return;
  color = (colorR << 16) + (colorG << 8) + colorB;
  if (colorB != (m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color & 0x0000ff))
  {
    m_pMathModel->planetSystem[planetsComboBox->currentIndex()].color = color;
    emit mathModelChanged();
  }
}